﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
using ImageUploaderComponent.Data;
using ImageUploaderComponent.Extensions;

namespace ImageUploaderComponent {
    public partial class DataGridView : IDataGridView {
        public event GridSelectionChangedHandler SelectionChanged;
        public delegate void GridSelectionChangedHandler(Object sender, ImageDataViewModel data);
        public event UploadingRowLoadedHandler UploadingRowLoaded;
        public delegate void UploadingRowLoadedHandler(DataGridRow row);

        private UploaderViewModel myViewModel = null;


        public DataGridView() {
            InitializeComponent();
            ItemsGrid.LoadingRow += itemsGridLoadingRow;
            ItemsGrid.CellEditEnded += itemsGridCellEditEnded;
            ItemsGrid.SelectionChanged += itemsGridSelectionChanged;

            Loaded += dataGridViewLoaded;


        }


        void dataGridViewLoaded(object sender, RoutedEventArgs e) {
            myViewModel = (UploaderViewModel)DataContext;
            ItemsGrid.ItemsSource = myViewModel.ImageDataList;
        }

        void itemsGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
            if (SelectionChanged != null && e.AddedItems.Count > 0) {
                SelectionChanged(sender, e.AddedItems != null ? (ImageDataViewModel)e.AddedItems[0] : null);
            }
        }

        public ImageDataViewModel SelectedItem {
            get {
                var item = ItemsGrid.SelectedItem as ImageDataViewModel;
                return item;
            }
        }

        public UploaderViewModel ItemsSource {
            get {
                return itemsSource;
            }
            set {
                //ItemsGrid.ItemsSource = value.ImageDataList;
                var trash = new ObservableCollection<ImageDataViewModel>();

            }
        }

        public void HideProgressColumn() {
            DataGridColumn description =
                ItemsGrid.Columns.Where(c => ((string)c.Header).ToLower() == "comment text").FirstOrDefault();
            DataGridColumn progress = ItemsGrid.Columns.Where(c => ((string)c.Header).ToLower() == "progress").FirstOrDefault();
            progress.MinWidth = 0;
            progress.MaxWidth = 0.1;
            progress.Width = new DataGridLength(0,DataGridLengthUnitType.Pixel);

            description.MaxWidth = 310;
            description.Width = new DataGridLength(310,DataGridLengthUnitType.Pixel);
        }

        public void ShowProgressColumn() {
            DataGridColumn description =
                ItemsGrid.Columns.Where(c => ((string)c.Header).ToLower() == "comment text").FirstOrDefault();
            DataGridColumn progress = ItemsGrid.Columns.Where(c => ((string)c.Header).ToLower() == "progress").FirstOrDefault();
            description.MinWidth = 0;
            description.MaxWidth = 0.01;
            description.Width = new DataGridLength(0,DataGridLengthUnitType.Pixel);


            progress.Width = new DataGridLength(300,DataGridLengthUnitType.Pixel);
            
        }

        public void Filter(MediaType mediaType){
            if(mediaType == MediaType.Demo){
                ItemsGrid.ItemsSource = myViewModel.DemoDataList;
            }
            else{
                ItemsGrid.ItemsSource = myViewModel.ImageDataList;
            }
        }



        public static readonly DependencyProperty DataContextWatcherProperty =
            DependencyProperty.Register("DataContextWatcher",
                                typeof(Object), typeof(DataGridView),
                                new PropertyMetadata(dataContextChanged));



        private static void dataContextChanged(object sender,
                                               DependencyPropertyChangedEventArgs e) {
            var control = (DataGridView)sender;
            var viewmodel = (UploaderViewModel)e.NewValue;
            control.ItemsGrid.ItemsSource = viewmodel.ImageDataList;
            // Update the control as needed
        }



        void itemsGridCellEditEnded(object sender, DataGridCellEditEndedEventArgs e) {
            var data = ((ImageDataViewModel)e.Row.DataContext);
            if (data.IsEnabled) {
                setRowEnabled(e.Row);
                return;
            }
            setRowDisabled(e.Row);

        }

        void itemsGridLoadingRow(object sender, DataGridRowEventArgs e) {

            var sourceColumn = ItemsGrid.Columns.Where(c => c.Header.ToString() == "Enabled").FirstOrDefault();
            if (sourceColumn != null) {
                var data = ((ImageDataViewModel)e.Row.DataContext);
                if (!data.IsEnabled) {
                    setRowDisabled(e.Row);
                }
                if (data.IsUploading && UploadingRowLoaded != null) {
                    UploadingRowLoaded(e.Row);
                }
                
            }


        }

        private void setRowEnabled(DataGridRow row) {
            row.Foreground = new SolidColorBrush(Colors.Black);
        }

        private void setRowDisabled(DataGridRow row) {
            row.Foreground = new SolidColorBrush(Colors.Gray);
        }



        private void rowEnabledCheckClick(object sender, RoutedEventArgs e) {
            var data = ((CheckBox)sender).Tag as ImageDataViewModel;
            if (data != null) {
                data.IsEnabled = !data.IsEnabled;
                var row = DataGridRow.GetRowContainingElement((FrameworkElement)sender);
                if (row != null) {
                    if (data.IsEnabled) {
                        setRowEnabled(row);
                    }
                    else {
                        setRowDisabled(row);
                    }

                }
            }
        }

        private void buttonMoveUpClick(object sender, RoutedEventArgs e) {
            int index = ItemsGrid.SelectedIndex;
            var viewModel = (UploaderViewModel)DataContext;
            if (index > 0) {
                var currentItem = viewModel.ImageDataList[index];
                var previousItem = viewModel.ImageDataList[index - 1];
                currentItem.DisplayOrder = index - 1;
                previousItem.DisplayOrder = index;
                viewModel.ImageDataList = viewModel.ImageDataList.OrderBy(i => i.DisplayOrder).ToObservable();
                ItemsGrid.ItemsSource = viewModel.ImageDataList;

                ItemsGrid.SelectedIndex = index - 1;

            }
        }

        private void buttonMoveDownClick(object sender, RoutedEventArgs e) {
            int index = ItemsGrid.SelectedIndex;
            var viewModel = (UploaderViewModel)DataContext;
            if (index < viewModel.ImageDataList.Count - 1) {
                var currentItem = viewModel.ImageDataList[index];
                var previousItem = viewModel.ImageDataList[index + 1];
                currentItem.DisplayOrder = index + 1;
                previousItem.DisplayOrder = index;
                viewModel.ImageDataList = viewModel.ImageDataList.OrderBy(i => i.DisplayOrder).ToObservable();
                ItemsGrid.ItemsSource = viewModel.ImageDataList;
                ItemsGrid.SelectedIndex = index + 1;
            }
        }

        private bool timerIsRunning = false;
        private FrameworkElement itemHoveredOver;

        private Point pointOfHover;
        private Canvas realRoot;
        private DispatcherTimer timer;
        private UploaderViewModel itemsSource;
        private Size requestedSize;


        private void textBoxFileNameMouseEnter(object sender, MouseEventArgs e){
            handleMouseEnter(e, sender, Constants.SmallImageSize);
        }

        private void TextBoxLargeFileName_MouseEnter(object sender, MouseEventArgs e) {
            //handleMouseEnter(e,sender,Constants.LargeImageSize);
        }


        private void handleMouseEnter(MouseEventArgs e, object sender, Size requestedSize){
            if (realRoot == null) {
                realRoot = new TreeHelper().FindParentWithName<Canvas>("LayoutCanvas", this);
            }
            this.requestedSize = requestedSize;
            //Set timer to implement hover delay
            if (!timerIsRunning) {
                pointOfHover = e.GetPosition(realRoot);
                timer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 1) };
                timer.Tick += timer_Tick;
                timerIsRunning = true;
                itemHoveredOver = sender as FrameworkElement;
                timer.Start();
            }
        }

        void timer_Tick(object sender, EventArgs e) {
            showImage(sender);
        }

        private void showImage(object state) {
            timer.Stop();

            var row = DataGridRow.GetRowContainingElement(itemHoveredOver);
            var data = (ImageDataViewModel)row.DataContext;
            if(data.Status == UploadStatus.InvalidExtension){
                return;
            }
            var helper = new ImageHelper();
            helper.showImage(realRoot, data, pointOfHover, requestedSize);
            timer = null;
        }



        private void TextBoxFileName_MouseLeave(object sender, MouseEventArgs e) {
            if (timerIsRunning) {
                if (timer != null) {
                    timer.Stop();
                }
                timerIsRunning = false;
                itemHoveredOver = null;
            }
        }



    }
}
